package com.bsj.power.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsj.power.common.config.cached.RedisCached;
import com.bsj.power.common.config.exception.ApiException;
import com.bsj.power.common.config.global.JsonResult;
import com.bsj.power.common.config.global.JsonResultEnum;
import com.bsj.power.common.config.redis.RedisConstant;
import com.bsj.power.common.config.rocketmq.producer.BaseMqPushUtil;
import com.bsj.power.common.constant.MqTopicAndTagConstants;
import com.bsj.power.common.def.dto.PageDTO;
import com.bsj.power.common.def.dto.ai.AiAlarmDTO;
import com.bsj.power.common.def.entity.ai.AiAlarm;
import com.bsj.power.common.def.entity.path.Path;
import com.bsj.power.common.def.vo.web.system.ai.AnnexStatVO;
import com.bsj.power.common.def.vo.web.system.ai.count.AnnexAreaNum;
import com.bsj.power.common.def.vo.web.system.ai.count.AnnexDayNum;
import com.bsj.power.common.def.vo.web.system.ai.count.AnnexTypeNum;
import com.bsj.power.common.file.web.MediaFileUtil;
import com.bsj.power.common.mapper.AiAlarmMapper;
import com.bsj.power.common.mapper.PathMapper;
import com.bsj.power.common.util.DateUtils;
import com.bsj.power.system.service.AiAlarmService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.bsj.power.common.util.DateUtils.yearMonthDay;

/**
 * @author yinhao
 * @version 1.0
 * @description AI报警附件实现类
 * @date 2024/6/26
 */
@Service
@Slf4j
public class AiAlarmServiceImpl implements AiAlarmService {

    @Resource
    private PathMapper pathMapper;

    @Resource
    private AiAlarmMapper aiAlarmMapper;

    @Autowired
    private RedisCached redisCached;

    @Autowired
    private BaseMqPushUtil baseMqPushUtil;

    /**
     * 新增修改AI报警附件
     * @param vo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addAndUpdateAi(AiAlarmDTO vo) {
        AiAlarm aiAlarm = new AiAlarm();
        Path path = pathMapper.selectOne(Wrappers.<Path>lambdaQuery().eq(Path::getPathName, vo.getAlarmName()));
        if (path == null) {
            throw new ApiException(JsonResultEnum.PATH_NOT_EXIST);
        }
        BeanUtil.copyProperties(vo, aiAlarm);
        int insert = 0;
        if (vo.getAiId() == null) {
            //新增
            insert = aiAlarmMapper.insert(aiAlarm);
        }
        return insert;
    }

    /**
     * 分页获取AI报警附件列表
     * @param dto 分页信息
     * @param alarmName 报警名称
     * @return
     */
    @Override
    public JsonResult<List<AiAlarm>> pageList(PageDTO dto, String alarmName) {
        IPage<AiAlarm> page = new Page<>(dto.getPageNumber(), dto.getPageSize());
        QueryWrapper<AiAlarm> queryWrapper = new QueryWrapper<>();
        if (dto.getStartTime() != null && dto.getEndTime() != null) {
            queryWrapper.lambda().between(AiAlarm::getCreateTime, dto.getStartTime(), dto.getEndTime());
        }
        if (alarmName != null) {
            queryWrapper.lambda().like(AiAlarm::getAlarmName, alarmName);
        }
        queryWrapper.lambda().orderByDesc(AiAlarm::getCreateTime);
        IPage<AiAlarm> iPage = aiAlarmMapper.selectPage(page, queryWrapper);
        return JsonResult.success(iPage.getRecords(), iPage.getTotal());
    }

    /**
     * 删除AI报警附件
     * @param aiId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteAiAnnex(Long aiId) {
        AiAlarm aiAlarm = aiAlarmMapper.selectById(aiId);
        if (aiAlarm == null) {
            return 0;
        }
        String mediaUrl = aiAlarm.getMediaUrl();
        if (mediaUrl != null) {
            //先删除文件
            MediaFileUtil.delete(mediaUrl);
        }
        return aiAlarmMapper.deleteById(aiId);
    }


    /**
     * 报警附件数据分析
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return
     */
    @Override
    public AnnexStatVO analysisAiAnnex(String startTime, String endTime) {
        Date start = null;
        Date end = null;
        if (startTime != null && endTime != null) {
            start = DateUtils.strToDate(startTime);
            end = DateUtils.strToDate(endTime);
        } else {
            //没有时间查询条件则默认查询近七天
            end = new Date();
            start = DateUtils.nDaysAgo(LocalDateTime.now(), 6);
        }
        QueryWrapper<AiAlarm> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().between(AiAlarm::getCreateTime, start, end);
        //获取符合要求的数据
        List<AiAlarm> aiAlarms = aiAlarmMapper.selectList(queryWrapper);
        AnnexStatVO vo = new AnnexStatVO();
        if (aiAlarms.isEmpty()) {
            return vo;
        }
        //按照附件类型分类
        Map<Integer, List<AiAlarm>> aiTypeMap = aiAlarms.stream().collect(Collectors.groupingBy(AiAlarm::getMediaType));
        //附件类型分布
        List<AnnexTypeNum> annexTypeNums = new ArrayList<>();
        aiTypeMap.forEach((key, value) -> {
            AnnexTypeNum annexTypeNum = AnnexTypeNum.builder().build();
            if (key == 1) {
                //图片
                annexTypeNum.setType("图片");
            } else {
                //视频
                annexTypeNum.setType("视频");
            }
            annexTypeNum.setCount(value.size());
            annexTypeNums.add(annexTypeNum);
        });
        vo.setAnnexTypeNums(annexTypeNums);

        //计算每日的报警附件数量
        List<AnnexDayNum> annexDayNums = new ArrayList<>();
        //根据开始时间和结束时间计算近几日作业列表
        List<String> dateAfter = DateUtils.getDateAfter(startTime, endTime);
        for (int i = dateAfter.size() - 1; i >= 0; i--) {
            //real time
            Date day = DateUtils.nDaysAgo(LocalDateTime.now(), i);
            // 获取当前天开始和结束的时间
            Date currentStart = DateUtils.getStartOfDay(day);
            Date currentEnd = DateUtils.getEndOfDay(day);
            //当前天所有的报警数
            long dayCount = aiAlarms.stream().filter(item -> item.getCreateTime().getTime() >= currentStart.getTime()
                    && item.getCreateTime().getTime() <= currentEnd.getTime()).count();
            String dateToStr = DateUtils.dateToStr(yearMonthDay, day);
            annexDayNums.add(AnnexDayNum.builder()
                    .time(dateToStr)
                    .num(dayCount)
                    .build());
        }
        vo.setAnnexDayNums(annexDayNums);

        //按区域统计附件排行数量
        List<AnnexAreaNum> annexAreaNums = new ArrayList<>();
        Map<String, Long> areaNumMap = aiAlarms.stream().collect(Collectors.groupingBy(AiAlarm::getAlarmArea, Collectors.counting()));
        areaNumMap.forEach((area, count) -> {
            AnnexAreaNum annexAreaNum = AnnexAreaNum.builder()
                    .areaName(area)
                    .num(count)
                    .build();
            annexAreaNums.add(annexAreaNum);
        });
        //让数据好看将数据进行排序(倒序)
        annexAreaNums.sort(Comparator.comparingLong(AnnexAreaNum::getNum).reversed());
        vo.setAnnexAreaNums(annexAreaNums);
        return vo;
    }

    /**
     * 计算作业人员异常
     * @param time
     */
//    @Override
//    public void anomalousJob(String time) {
//        String s = redisCached.get(RedisConstant.ANOMALOUS_JOB_TASK_TIME + time);
//        if (s != null) {
//            log.info("该时段任务已经被执行Time: {}", time);
//            return;
//        }
//        //定时一分钟过期
//        redisCached.set(RedisConstant.ANOMALOUS_JOB_TASK_TIME + time, time, 60);
//        baseMqPushUtil.sendTopicBytes(MqTopicAndTagConstants.BASE_SERVER_CHANGE_TOPIC,
//                MqTopicAndTagConstants.BASE_TASK_JOB_ANOMALOUS_TAG, time.getBytes());
//    }
}
